home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
src
/
apply.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-19
|
53KB
|
2,111 lines
/* SCCS Id: @(#)apply.c 3.1 92/12/10 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "edog.h"
#ifdef OVLB
static const char NEARDATA tools[] = { TOOL_CLASS, 0 };
static boolean NEARDATA did_dig_msg;
#ifdef TOURIST
static int FDECL(use_camera, (struct obj *));
#endif
static int FDECL(use_towel, (struct obj *));
static void FDECL(use_stethoscope, (struct obj *));
static void FDECL(use_whistle, (struct obj *));
static void FDECL(use_magic_whistle, (struct obj *));
#ifdef WALKIES
static void FDECL(use_leash, (struct obj *));
#endif
STATIC_DCL int NDECL(dig);
#ifdef OVLB
STATIC_DCL schar FDECL(fillholetyp, (int, int));
#endif
static boolean FDECL(wield_tool, (struct obj *));
static int FDECL(use_pick_axe, (struct obj *));
static int FDECL(use_mirror, (struct obj *));
static void FDECL(use_bell, (struct obj *));
static void FDECL(use_candelabrum, (struct obj *));
static void FDECL(use_candle, (struct obj *));
static void FDECL(use_lamp, (struct obj *));
static void FDECL(use_tinning_kit, (struct obj *));
static void FDECL(use_figurine, (struct obj *));
static void FDECL(use_grease, (struct obj *));
static boolean NDECL(rm_waslit);
static void FDECL(mkcavepos, (XCHAR_P,XCHAR_P,int,BOOLEAN_P,BOOLEAN_P));
static void FDECL(mkcavearea, (BOOLEAN_P));
#ifdef TOURIST
static int
use_camera(obj)
struct obj *obj;
{
register struct monst *mtmp;
if(Underwater) {
pline("Using your camera underwater voids the warranty.");
return(0);
}
if(!getdir(NULL)) return(0);
if(u.uswallow) {
You("take a picture of %s's %s.", mon_nam(u.ustuck),
is_animal(u.ustuck->data) ? "stomach" : "interior");
} else if(obj->cursed && !rn2(2)) goto blindu;
else if(u.dz) {
You("take a picture of the %s.",
(u.dz > 0) ? "floor" : "ceiling");
} else if(!u.dx && !u.dy) {
blindu:
if(!Blind) {
You("are blinded by the flash!");
make_blinded((long)rnd(25),FALSE);
}
} else if(mtmp = bhit(u.dx,u.dy,COLNO,FLASHED_LIGHT,
(int(*)())0,(int(*)())0,obj)) {
if(mtmp->msleep) {
mtmp->msleep = 0;
if(cansee(mtmp->mx,mtmp->my))
pline("The flash awakens %s.", mon_nam(mtmp)); /* a3 */
} else if (mtmp->data->mlet != S_LIGHT)
if((mtmp->mcansee && haseyes(mtmp->data))
|| mtmp->mblinded) {
register int tmp = distu(mtmp->mx,mtmp->my);
register int tmp2;
if(cansee(mtmp->mx,mtmp->my))
pline("%s is blinded by the flash!", Monnam(mtmp));
if(mtmp->data == &mons[PM_GREMLIN]) {
/* Rule #1: Keep them out of the light. */
pline("%s cries out in pain!", Monnam(mtmp));
if (mtmp->mhp > 1) mtmp->mhp--;
}
setmangry(mtmp);
if(tmp < 9 && !mtmp->isshk && rn2(4)) {
mtmp->mflee = 1;
if(rn2(4)) mtmp->mfleetim = rnd(100);
}
mtmp->mcansee = 0;
if(tmp < 3) {
mtmp->mblinded = 0;
} else {
tmp2 = mtmp->mblinded;
tmp2 += rnd(1 + 50/tmp);
if(tmp2 > 127) tmp2 = 127;
mtmp->mblinded = tmp2;
}
}
}
return 1;
}
#endif
static int
use_towel(obj)
struct obj *obj;
{
if(!freehand()) {
You("have no free %s!", body_part(HAND));
return 0;
} else if (obj->owornmask) {
You("can't use it while you're wearing it!");
return 0;
} else if (obj->cursed) {
long old;
switch (rn2(3)) {
case 2:
old = Glib;
Glib += rn1(10, 3);
Your("%s are %s!", makeplural(body_part(HAND)),
(old ? "filthier than ever" : "now slimy"));
return 1;
case 1:
if (!Blindfolded) {
old = u.ucreamed;
u.ucreamed += rn1(10, 3);
pline("Yecch! Your %s %s gunk on it!", body_part(FACE),
(old ? "has more" : "now has"));
make_blinded(Blinded + (long)u.ucreamed - old, TRUE);
} else {
if (ublindf->cursed) {
You("pushed your blindfold %s.",
rn2(2) ? "cock-eyed" : "crooked");
} else {
You("pushed your blindfold off.");
Blindf_off(ublindf);
dropx(ublindf);
}
}
return 1;
case 0:
break;
}
}
if (Glib) {
Glib = 0;
You("wipe off your %s.", makeplural(body_part(HAND)));
return 1;
} else if(u.ucreamed) {
Blinded -= u.ucreamed;
u.ucreamed = 0;
if (!Blinded) {
pline("You've got the glop off.");
Blinded = 1;
make_blinded(0L,TRUE);
} else {
Your("%s feels clean now.", body_part(FACE));
}
return 1;
}
Your("%s and %s are already clean.",
body_part(FACE), makeplural(body_part(HAND)));
return 0;
}
static char hollow_str[] = "hear a hollow sound! This must be a secret %s!";
/* Strictly speaking it makes no sense for usage of a stethoscope to
not take any time; however, unless it did, the stethoscope would be
almost useless. */
static void
use_stethoscope(obj)
register struct obj *obj;
{
register struct monst *mtmp;
register struct rm *lev;
register int rx, ry;
if(!freehand()) {
You("have no free %s!", body_part(HAND));
return;
}
if (!getdir(NULL)) return;
if (u.uswallow && (u.dx || u.dy || u.dz)) {
mstatusline(u.ustuck);
return;
} else if (u.dz) {
if (Underwater)
You("hear faint splashing.");
else if (u.dz < 0 || Levitation)
You("can't reach the %s!", u.dz<0 ? "ceiling" : "floor");
else if (Is_stronghold(&u.uz))
You("hear the crackling of hellfire.");
else
pline("The floor seems healthy enough.");
return;
} else if (obj->cursed && !rn2(2)) {
You("hear your heart beat.");
return;
}
if (Stunned || (Confusion && !rn2(5))) confdir();
if (!u.dx && !u.dy) {
ustatusline();
return;
}
rx = u.ux + u.dx; ry = u.uy + u.dy;
if (!isok(rx,ry)) {
You("hear a faint typing noise.");
return;
}
if(mtmp = m_at(rx,ry)) {
mstatusline(mtmp);
if (mtmp->mundetected) {
mtmp->mundetected = 0;
if (cansee(rx,ry)) newsym(mtmp->my,mtmp->my);
}
return;
}
lev = &levl[rx][ry];
switch(lev->typ) {
case SDOOR:
You(hollow_str, "door");
lev->typ = DOOR;
newsym(rx,ry);
return;
case SCORR:
You(hollow_str, "passage");
lev->typ = CORR;
newsym(rx,ry);
return;
}
You("hear nothing special.");
}
static char whistle_str[] = "produce a %s whistling sound.";
/*ARGSUSED*/
static void
use_whistle(obj)
struct obj *obj;
{
You(whistle_str, "high");
wake_nearby();
}
static void
use_magic_whistle(obj)
struct obj *obj;
{
register struct monst *mtmp;
if(obj->cursed && !rn2(2)) {
You("produce a high-pitched humming noise.");
wake_nearby();
} else {
makeknown(MAGIC_WHISTLE);
You(whistle_str, Hallucination ? "normal" : "strange");
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if(mtmp->mtame) mnexto(mtmp);
}
}
boolean
um_dist(x,y,n)
register xchar x, y, n;
{
return(abs(u.ux - x) > n || abs(u.uy - y) > n);
}
#endif /* OVLB */
#ifdef WALKIES
#define MAXLEASHED 2
#ifdef OVLB
int
number_leashed()
{
register int i = 0;
register struct obj *obj;
for(obj = invent; obj; obj = obj->nobj)
if(obj->otyp == LEASH && obj->leashmon != 0) i++;
return(i);
}
void
o_unleash(otmp) /* otmp is about to be destroyed or stolen */
register struct obj *otmp;
{
register struct monst *mtmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if(mtmp->m_id == (unsigned)otmp->leashmon)
mtmp->mleashed = 0;
otmp->leashmon = 0;
}
void
m_unleash(mtmp) /* mtmp is about to die, or become untame */
register struct monst *mtmp;
{
register struct obj *otmp;
for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp->otyp == LEASH &&
otmp->leashmon == (int)mtmp->m_id)
otmp->leashmon = 0;
mtmp->mleashed = 0;
}
void
unleash_all() /* player is about to die (for bones) */
{
register struct obj *otmp;
register struct monst *mtmp;
for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp->otyp == LEASH) otmp->leashmon = 0;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if(mtmp->mtame) mtmp->mleashed = 0;
}
/* ARGSUSED */
static void
use_leash(obj)
struct obj *obj;
{
register int x, y;
register struct monst *mtmp;
int spotmon;
if(!obj->leashmon && number_leashed() >= MAXLEASHED) {
You("can't leash additional pets.");
return;
}
if(!getdir(NULL)) return;
x = u.ux + u.dx;
y = u.uy + u.dy;
if((x == u.ux) && (y == u.uy)) {
pline("Leash yourself? Very funny...");
return;
}
if(!(mtmp = m_at(x, y))) {
pline("There is no creature here.");
return;
}
spotmon = canseemon(mtmp) || sensemon(mtmp);
if(!mtmp->mtame) {
if(!spotmon)
pline("There is no creature here.");
else
pline("%s is not %s!", Monnam(mtmp), (!obj->leashmon) ?
"leashable" : "leashed");
return;
}
if(!obj->leashmon) {
if(mtmp->mleashed) {
pline("This %s is already leashed!",
spotmon ? l_monnam(mtmp) : "monster");
return;
}
You("slip the leash around %s%s.",
spotmon ? "your " : "", l_monnam(mtmp));
mtmp->mleashed = 1;
obj->leashmon = (int)mtmp->m_id;
if(mtmp->msleep) mtmp->msleep = 0;
return;
}
if(obj->leashmon != (int)mtmp->m_id) {
pline("This leash is not attached to that creature!");
return;
} else {
if(obj->cursed) {
pline("The leash wouldn't come off!");
return;
}
mtmp->mleashed = 0;
obj->leashmon = 0;
You("remove the leash from %s%s.",
spotmon ? "your " : "", l_monnam(mtmp));
}
return;
}
#endif /* OVLB */
#ifdef OVL1
boolean
next_to_u()
{
register struct monst *mtmp;
register struct obj *otmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if(mtmp->mleashed) {
if (distu(mtmp->mx,mtmp->my) > 2) mnexto(mtmp);
if (distu(mtmp->mx,mtmp->my) > 2) {
for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp->otyp == LEASH &&
otmp->leashmon == (int)mtmp->m_id) {
if(otmp->cursed) return(FALSE);
You("feel %s leash go slack.",
(number_leashed() > 1) ? "a" : "the");
mtmp->mleashed = 0;
otmp->leashmon = 0;
}
}
}
return(TRUE);
}
#endif /* OVL1 */
#ifdef OVLB
struct obj *
get_mleash(mtmp) /* assuming mtmp->mleashed has been checked */
register struct monst *mtmp;
{
register struct obj *otmp;
otmp = invent;
while(otmp) {
if(otmp->otyp == LEASH && otmp->leashmon == (int)mtmp->m_id)
return(otmp);
otmp = otmp->nobj;
}
return((struct obj *)0);
}
#endif /* OVLB */
#endif /* WALKIES */
#ifdef OVL0
#ifdef WALKIES
void
check_leash(x, y)
register xchar x, y;
{
register struct obj *otmp;
register struct monst *mtmp = fmon;
for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp->otyp == LEASH && otmp->leashmon != 0) {
while(mtmp) {
if((int)mtmp->m_id == otmp->leashmon &&
(dist2(u.ux,u.uy,mtmp->mx,mtmp->my) >
dist2(x,y,mtmp->mx,mtmp->my))
) {
if(otmp->cursed) {
if(um_dist(mtmp->mx, mtmp->my, 5)) {
pline("%s chokes to death!",Monnam(mtmp));
mondied(mtmp);
} else
if(um_dist(mtmp->mx, mtmp->my, 3))
pline("%s chokes on the leash!",
Monnam(mtmp));
} else {
if(um_dist(mtmp->mx, mtmp->my, 5)) {
pline("%s's leash snaps loose!",Monnam(mtmp));
m_unleash(mtmp);
} else {
if(um_dist(mtmp->mx, mtmp->my, 3)) {
You("pull on the leash.");
# ifdef SOUNDS
if (mtmp->data->msound != MS_SILENT)
switch(rn2(3)) {
case 0: growl(mtmp); break;
case 1: yelp(mtmp); break;
default: whimper(mtmp); break;
}
# endif
}
}
}
}
mtmp = mtmp->nmon;
}
}
}
#endif /* WALKIES */
#endif /* OVL0 */
#ifdef OVLB
static boolean
rm_waslit() {
register xchar x, y;
if(levl[u.ux][u.uy].typ == ROOM && levl[u.ux][u.uy].waslit)
return(TRUE);
for(x = u.ux-2; x < u.ux+3; x++)
for(y = u.uy-1; y < u.uy+2; y++)
if(isok(x,y) && levl[x][y].waslit) return(TRUE);
return(FALSE);
}
/* Change level topology. Messes with vision tables and ignores things like
* boulders in the name of a nice effect. Vision will get fixed up again
* immediately after the effect is complete.
*/
static void
mkcavepos(x, y, dist, waslit, rockit)
xchar x,y;
int dist;
boolean waslit, rockit;
{
register struct rm *lev;
if(!isok(x,y)) return;
lev = &levl[x][y];
if(rockit) {
register struct monst *mtmp;
if(IS_ROCK(lev->typ)) return;
if(t_at(x, y)) return; /* don't cover the portal */
if(mtmp = m_at(x, y)) /* make sure crucial monsters survive */
if(!passes_walls(mtmp->data)) rloc(mtmp);
} else if(lev->typ == ROOM) return;
unblock_point(x,y); /* make sure vision knows this location is open */
/* fake out saved state */
lev->seen = FALSE;
lev->doormask = 0;
if(dist < 3) lev->lit = (rockit ? FALSE : TRUE);
if(waslit) lev->waslit = (rockit ? FALSE : TRUE);
lev->horizontal = FALSE;
viz_array[y][x] = (dist < 3 ) ?
(IN_SIGHT|COULD_SEE) : /* short-circuit vision recalc */
COULD_SEE;
lev->typ = (rockit ? STONE : ROOM);
if(dist >= 3)
impossible("mkcavepos called with dist %d", dist);
if(Blind)
feel_location(x, y);
else newsym(x,y);
}
static void
mkcavearea(rockit)
register boolean rockit;
{
int dist;
xchar xmin = u.ux, xmax = u.ux;
xchar ymin = u.uy, ymax = u.uy;
register xchar i;
register boolean waslit = rm_waslit();
if(rockit) pline("Crash! The ceiling collapses around you!");
else pline("A mysterious force %s cave around you!",
(levl[u.ux][u.uy].typ == CORR) ? "creates a" : "extends the");
display_nhwindow(WIN_MESSAGE, TRUE);
for(dist = 1; dist <= 2; dist++) {
xmin--; xmax++;
/* top and bottom */
if(dist < 2) { /* the area is wider that it is high */
ymin--; ymax++;
for(i = xmin+1; i < xmax; i++) {
mkcavepos(i, ymin, dist, waslit, rockit);
mkcavepos(i, ymax, dist, waslit, rockit);
}
}
/* left and right */
for(i = ymin; i <= ymax; i++) {
mkcavepos(xmin, i, dist, waslit, rockit);
mkcavepos(xmax, i, dist, waslit, rockit);
}
flush_screen(1); /* make sure the new glyphs shows up */
delay_output();
}
if(!rockit && levl[u.ux][u.uy].typ == CORR) {
levl[u.ux][u.uy].typ = ROOM;
if(waslit) levl[u.ux][u.uy].waslit = TRUE;
newsym(u.ux, u.uy); /* in case player is invisible */
}
vision_full_recalc = 1; /* everything changed */
}
STATIC_OVL int
dig()
{
register struct rm *lev;
register xchar dpx = dig_pos.x, dpy = dig_pos.y;
lev = &levl[dpx][dpy];
/* perhaps a nymph stole your pick-axe while you were busy digging */
/* or perhaps you teleported away */
if(u.uswallow || !uwep || uwep->otyp != PICK_AXE ||
!on_level(&dig_level, &u.uz) ||
((dig_down && (dpx != u.ux || dpy != u.uy)) ||
(!dig_down && distu(dpx,dpy) > 2)))
return(0);
if (dig_down) {
if(On_stairs(u.ux, u.uy)) {
if(u.ux == xdnladder || u.ux == xupladder)
pline("The ladder resists your effort.");
else pline("The stairs here are too hard to dig in.");
return(0);
}
if(IS_THRONE(levl[u.ux][u.uy].typ)) {
pline("The throne here is too hard to break apart.");
return (0);
}
if(IS_ALTAR(levl[u.ux][u.uy].typ)) {
pline("The altar here is too hard to break apart.");
return (0);
}
if(t_at(dpx, dpy) && !Can_dig_down(&u.uz)) {
pline("The floor here is too hard to dig in.");
return(0);
}
if(sobj_at(BOULDER, dpx, dpy)) {
pline("There is not enough room here to dig.");
return(0);
}
if(Is_airlevel(&u.uz)) {
You("cannot dig in thin air.");
return(0);
}
if(Is_waterlevel(&u.uz)) {
pline("The water splashes and subsides.");
return(0);
}
} else /* !dig_down */
if(IS_ROCK(lev->typ) && !may_dig(dpx,dpy)) {
pline("This wall is too hard to dig into.");
return(0);
}
if(Fumbling && !rn2(3)) {
switch(rn2(3)) {
case 0: if(!welded(uwep)) {
You("fumble and drop your %s.", xname(uwep));
dropx(uwep);
setuwep((struct obj *)0);
} else {
pline("Ouch! Your %s bounces and hits you!",
xname(uwep));
set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
}
break;
case 1: pline("Bang! You hit with the broad side of %s!",
the(xname(uwep)));
break;
default: Your("swing misses its mark.");
break;
}
return(0);
}
dig_effort += 10 + abon() + uwep->spe - uwep->oeroded + rn2(5);
if(dig_down) {
register struct trap *ttmp;
if(dig_effort > 250) {
dighole();
dig_level.dnum = 0;
dig_level.dlevel = -1;
return(0); /* done with digging */
}
if (dig_effort <= 50)
return(1);
if ((ttmp = t_at(dpx,dpy)) &&
((ttmp->ttyp == PIT) || (ttmp->ttyp == SPIKED_PIT) ||
(ttmp->ttyp == TRAPDOOR)))
return(1);
if (IS_ALTAR(lev->typ)) {
altar_wrath(dpx, dpy);
angry_priest();
}
ttmp = maketrap(dpx,dpy,PIT);
ttmp->tseen = 1;
if(Invisible) newsym(ttmp->tx,ttmp->ty);
You("have dug a pit.");
u.utrap = rn1(4,2);
u.utraptype = TT_PIT;
vision_full_recalc = 1; /* vision limits change */
dig_level.dnum = 0;
dig_level.dlevel = -1;
return(0);
}
if(dig_effort > 100) {
register const char *digtxt, *dmgtxt = (const char*) 0;
register struct obj *obj;
register boolean shopedge = *in_rooms(dpx, dpy, SHOPBASE);
if(obj = sobj_at(STATUE, dpx, dpy)) {
if (break_statue(obj))
digtxt = "The statue shatters.";
else
/* it was a statue trap; break_statue()
* printed a message and updated the screen
*/
digtxt = NULL;
} else if(obj = sobj_at(BOULDER, dpx, dpy)) {
fracture_rock(obj);
digtxt = "The boulder falls apart.";
} else if(!lev->typ || lev->typ == SCORR) {
if(Is_earthlevel(&u.uz)) {
if(uwep->blessed && !rn2(3)) {
mkcavearea(FALSE);
goto cleanup;
} else if((uwep->cursed && !rn2(4)) ||
(!uwep->blessed && !rn2(6))) {
mkcavearea(TRUE);
goto cleanup;
}
}
lev->typ = CORR;
digtxt = "You succeeded in cutting away some rock.";
} else if(IS_WALL(lev->typ)) {
if(shopedge) {
add_damage(dpx, dpy, 10L * ACURRSTR);
dmgtxt = "dig into";
}
if (level.flags.is_maze_lev) {
lev->typ = ROOM;
} else if (level.flags.is_cavernous_lev) {
lev->typ = CORR;
} else {
lev->typ = DOOR;
lev->doormask = D_NODOOR;
}
digtxt = "You just made an opening in the wall.";
} else if(lev->typ == SDOOR) {
lev->typ = DOOR;
digtxt = "You just broke through a secret door.";
if(!(lev->doormask & D_TRAPPED))
lev->doormask = D_BROKEN;
} else if(closed_door(dpx, dpy)) {
digtxt = "You just broke a hole through the door.";
if(shopedge) {
add_damage(dpx, dpy, 400L);
dmgtxt = "break";
}
if(!(lev->doormask & D_TRAPPED))
lev->doormask = D_BROKEN;
} else return(0); /* statue or boulder got taken */
unblock_point(dpx,dpy); /* vision: can see through */
if(Blind)
feel_location(dpx, dpy);
else
newsym(dpx, dpy);
if(digtxt) pline(digtxt); /* after newsym */
if(dmgtxt)
pay_for_damage(dmgtxt);
if(Is_earthlevel(&u.uz) && !rn2(3)) {
register struct monst *mtmp;
switch(rn2(2)) {
case 0:
mtmp = makemon(&mons[PM_EARTH_ELEMENTAL], dpx, dpy);
break;
default:
mtmp = makemon(&mons[PM_XORN], dpx, dpy);
break;
}
if(mtmp) pline("The debris of your dig comes alive!");
}
if(IS_DOOR(lev->typ) && (lev->doormask & D_TRAPPED)) {
b_trapped("door");
lev->doormask = D_NODOOR;
newsym(dpx, dpy);
}
cleanup:
dig_level.dnum = 0;
dig_level.dlevel = -1;
return(0);
} else {
if(IS_WALL(lev->typ) || closed_door(dpx, dpy)) {
if(*in_rooms(dpx, dpy, SHOPBASE)) {
pline("This %s seems too hard to dig into.",
IS_DOOR(lev->typ) ? "door" : "wall");
return(0);
}
} else if (!IS_ROCK(lev->typ) && !sobj_at(STATUE, dpx, dpy)
&& !sobj_at(BOULDER, dpx, dpy))
return(0); /* statue or boulder got taken */
if(!did_dig_msg) {
You("hit the %s with all your might.",
sobj_at(STATUE, dpx, dpy) ? "statue" :
sobj_at(BOULDER, dpx, dpy) ? "boulder" :
IS_DOOR(lev->typ) ? "door" : "rock");
did_dig_msg = TRUE;
}
}
return(1);
}
/* When will hole be finished? Very rough indication used by shopkeeper. */
int
holetime() {
if(occupation != dig || !*u.ushops) return(-1);
return((250 - dig_effort)/20);
}
/* Return typ of liquid to fill a hole with, or ROOM, if no liquid nearby */
STATIC_OVL
schar
fillholetyp(x,y)
int x, y;
{
register int x1, y1;
for(x1 = max(1,x-1); x1<=min(x+1,COLNO-1); x1++)
for(y1 = max(0,y-1); y1<=min(y+1,ROWNO-1); y1++)
if(levl[x1][y1].typ == MOAT || levl[x1][y1].typ == LAVAPOOL)
return levl[x1][y1].typ;
return ROOM;
}
void
dighole()
{
register struct trap *ttmp = t_at(u.ux, u.uy);
struct rm *lev = &levl[u.ux][u.uy];
struct obj *boulder_here;
boolean nohole = !Can_dig_down(&u.uz);
if(ttmp && nohole) {
pline("The floor here seems too hard to dig in.");
} else {
d_level newlevel;
if (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) {
pline(
"The %s sloshes furiously for a moment, then subsides.",
is_lava(u.ux, u.uy) ? "lava" : "water");
return;
}
if (lev->typ == DRAWBRIDGE_DOWN) {
destroy_drawbridge(u.ux,u.uy);
return;
} else if (boulder_here = sobj_at(BOULDER, u.ux, u.uy)) {
if (ttmp && ((ttmp->ttyp == PIT) ||
(ttmp->ttyp == SPIKED_PIT))) {
pline("The boulder settles into the pit.");
ttmp->ttyp = PIT; /* crush spikes */
} else {
/*
* digging makes a hole, but the boulder
* immediately fills it. Final outcome:
* no hole, no boulder.
*/
pline("KADOOM! The boulder falls in!");
/* destroy traps that emanate from the floor */
/* some of these are arbitrary -dlc */
if (ttmp && ((ttmp->ttyp == SQKY_BOARD) ||
(ttmp->ttyp == BEAR_TRAP) ||
(ttmp->ttyp == LANDMINE) ||
(ttmp->ttyp == FIRE_TRAP) ||
(ttmp->ttyp == TRAPDOOR) ||
(ttmp->ttyp == TELEP_TRAP) ||
(ttmp->ttyp == LEVEL_TELEP) ||
(ttmp->ttyp == WEB) ||
(ttmp->ttyp == MAGIC_TRAP) ||
(ttmp->ttyp == ANTI_MAGIC))) {
deltrap(ttmp);
u.utrap = 0;
u.utraptype = 0;
}
}
delobj(boulder_here);
return;
}
if (lev->typ == DRAWBRIDGE_UP) {
/* must be floor or ice, other cases handled above */
/* dig "pit" and let fluid flow in (if possible) */
schar typ = fillholetyp(u.ux,u.uy);
if(typ == ROOM) {
if(lev->drawbridgemask & DB_ICE)
typ = MOAT;
else {
/*
* We can't dig a pit here since that will
* destroy the drawbridge. The following is
* a cop-out. --dlc
*/
pline("The floor here seems too hard to dig in.");
return;
}
}
lev->drawbridgemask &= DB_DIR;
if(typ == LAVAPOOL) lev->drawbridgemask |= DB_LAVA;
newsym(u.ux,u.uy);
pline("As you dig a pit, it fills with %s!",
typ == LAVAPOOL ? "lava" : "water");
if(!Levitation
#ifdef POLYSELF
&& !is_flyer(uasmon)
#endif
) {
if (typ == LAVAPOOL)
(void) lava_effects();
else if(!Wwalking)
(void) drown();
}
return;
} else if (lev->typ == ICE) {
/* assume we can remove most of the ice by drilling
* without melting it or allowing neighboring water
* to flow in.
*/
lev->typ = ROOM;
} else if (IS_FOUNTAIN(lev->typ)) {
dogushforth(FALSE);
dryup(u.ux,u.uy);
return;
#ifdef SINKS
} else if (IS_SINK(lev->typ)) {
breaksink(u.ux, u.uy);
return;
#endif
/* the following two are here for the wand of digging */
} else if(IS_THRONE(levl[u.ux][u.uy].typ)) {
pline("The throne here is too hard to break apart.");
return;
} else if(IS_ALTAR(levl[u.ux][u.uy].typ)) {
pline("The altar here is too hard to break apart.");
return;
} else if(ttmp) {
ttmp->ttyp = TRAPDOOR;
} else if(nohole) {
/* can't make a trapdoor, so make a pit */
ttmp = maketrap(u.ux, u.uy, PIT);
} else
ttmp = maketrap(u.ux, u.uy, TRAPDOOR);
ttmp->tseen = 1;
if(Invisible) newsym(ttmp->tx,ttmp->ty);
if(ttmp->ttyp == PIT) {
You("have dug a pit.");
if(!Levitation) {
u.utrap = rn1(4,2);
u.utraptype = TT_PIT;
vision_full_recalc = 1; /* vision limits change */
} else
u.utrap = 0;
return;
}
pline("You've made a hole in the floor.");
/* floor objects get a chance of falling down.
* the case where the hero does NOT fall down
* is treated here. the case where the hero
* does fall down is treated in goto_level().
*/
if(OBJ_AT(u.ux, u.uy) && (u.ustuck || Levitation
#ifdef WALKIES
|| !next_to_u()
#endif
))
impact_drop((struct obj *)0, u.ux, u.uy, 0);
if (*u.ushops)
add_damage(u.ux, u.uy, 0L);
if(!u.ustuck && !Levitation) { /* KAA */
if(*u.ushops)
shopdig(1);
#ifdef WALKIES
if(!next_to_u())
You("are jerked back by your pet!");
else
#endif
{
You("fall through...");
/* the checks above must ensure that */
/* the destination level exists and is */
/* in the present dungeon. */
newlevel.dnum = u.uz.dnum;
newlevel.dlevel = u.uz.dlevel + 1;
goto_level(&newlevel, FALSE, TRUE, FALSE);
}
}
}
}
static boolean
wield_tool(obj)
struct obj *obj;
{
if(welded(uwep)) {
/* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */
if(flags.verbose) {
pline("Since your weapon is welded to your %s,",
bimanual(uwep) ?
(const char *)makeplural(body_part(HAND))
: body_part(HAND));
pline("you cannot wield that %s.", xname(obj));
}
return(FALSE);
}
# ifdef POLYSELF
if(cantwield(uasmon)) {
You("can't hold it strongly enough.");
return(FALSE);
}
# endif
unweapon = TRUE;
You("now wield %s.", doname(obj));
setuwep(obj);
if (uwep != obj) return(FALSE); /* rewielded old object after dying */
return(TRUE);
}
static int
use_pick_axe(obj)
struct obj *obj;
{
char dirsyms[12];
char qbuf[QBUFSZ];
register char *dsp = dirsyms;
register const char *sdp = flags.num_pad ? ndir : sdir;
register struct rm *lev;
register int rx, ry, res = 0;
register boolean isclosedoor;
if(obj != uwep)
if (!wield_tool(obj)) return(0);
else res = 1;
while(*sdp) {
(void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */
rx = u.ux + u.dx;
ry = u.uy + u.dy;
if(u.dz > 0 || (u.dz == 0 && isok(rx, ry) &&
(IS_ROCK(levl[rx][ry].typ)
|| sobj_at(STATUE, rx, ry)
|| sobj_at(BOULDER, rx, ry))))
*dsp++ = *sdp;
sdp++;
}
*dsp = 0;
Sprintf(qbuf, "In what direction do you want to dig? [%s]", dirsyms);
if(!getdir(qbuf))
return(res);
if(u.uswallow && attack(u.ustuck)) /* return(1) */;
else if(Underwater) {
pline("Turbulence torpedoes your digging attempts.");
} else if(u.dz < 0) {
if(Levitation)
You("don't have enough leverage.");
else
You("cannot reach the ceiling.");
} else if(!u.dx && !u.dy && !u.dz) {
char buf[BUFSZ];
int dam;
dam = rnd(2) + dbon() + obj->spe;
if (dam <= 0) dam = 1;
You("hit yourself with your own pick-axe.");
/* self_pronoun() won't work twice in a sentence */
Strcpy(buf, self_pronoun("killed %sself with %%s own pick-axe",
"him"));
losehp(dam, self_pronoun(buf, "his"), NO_KILLER_PREFIX);
flags.botl=1;
return(1);
} else if(u.dz == 0) {
if(Stunned || (Confusion && !rn2(5))) confdir();
rx = u.ux + u.dx;
ry = u.uy + u.dy;
if(!isok(rx, ry)) {
pline("Clash!");
return(1);
}
lev = &levl[rx][ry];
if(MON_AT(rx, ry) && attack(m_at(rx, ry)))
return(1);
isclosedoor = closed_door(rx, ry);
if(!IS_ROCK(lev->typ)
&& !isclosedoor
&& !sobj_at(STATUE, rx, ry)
&& !sobj_at(BOULDER, rx, ry)) {
/* ACCESSIBLE or POOL */
You("swing your %s through thin air.",
aobjnam(obj, NULL));
} else {
if(dig_pos.x != rx || dig_pos.y != ry
|| !on_level(&dig_level, &u.uz) || dig_down) {
dig_down = FALSE;
dig_pos.x = rx;
dig_pos.y = ry;
assign_level(&dig_level, &u.uz);
dig_effort = 0;
You("start %s.",
sobj_at(STATUE, rx, ry) ?
"chipping the statue" :
sobj_at(BOULDER, rx, ry) ?
"hitting the boulder" :
isclosedoor ? "chopping at the door" :
"digging");
} else
You("continue %s.",
sobj_at(STATUE, rx, ry) ?
"chipping the statue" :
sobj_at(BOULDER, rx, ry) ?
"hitting the boulder" :
isclosedoor ? "chopping at the door" :
"digging");
did_dig_msg = FALSE;
set_occupation(dig, "digging", 0);
}
} else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
/* it must be air -- water checked above */
You("swing your %s through thin air.", aobjnam(obj, NULL));
} else if(Levitation) {
You("cannot reach the floor.");
} else if (is_pool(u.ux, u.uy)) {
/* Monsters which swim also happen not to be able to dig */
You("cannot stay underwater long enough.");
} else {
if(dig_pos.x != u.ux || dig_pos.y != u.uy
|| !on_level(&dig_level, &u.uz) || !dig_down) {
dig_down = TRUE;
dig_pos.x = u.ux;
dig_pos.y = u.uy;
assign_level(&dig_level, &u.uz);
dig_effort = 0;
You("start digging in the floor.");
if(*u.ushops)
shopdig(0);
} else
You("continue digging in the floor.");
did_dig_msg = FALSE;
set_occupation(dig, "digging", 0);
}
return(1);
}
#define WEAK 3 /* from eat.c */
static char look_str[] = "look %s.";
static int
use_mirror(obj)
struct obj *obj;
{
register struct monst *mtmp;
register char mlet;
boolean vis;
if(!getdir(NULL)) return 0;
if(obj->cursed && !rn2(2)) {
if (!Blind)
pline("The mirror fogs up and doesn't reflect!");
return 1;
}
if(!u.dx && !u.dy && !u.dz) {
if(!Blind && !Invisible) {
#ifdef POLYSELF
if(u.umonnum == PM_FLOATING_EYE) {
pline(Hallucination ?
"Yow! The mirror stared back at you!" :
"Yikes! You've frozen yourself!");
nomul(-rnd((MAXULEV+6) - (int)u.ulevel));
} else if (u.usym == S_VAMPIRE)
You("don't seem to reflect anything.");
else if(u.umonnum == PM_UMBER_HULK) {
pline("Huh? That doesn't look like you!");
make_confused(HConfusion + d(3,4),FALSE);
} else
#endif
if (Hallucination) You(look_str, hcolor());
else if (Sick)
You(look_str, "peaked");
else if (u.uhs >= WEAK)
You(look_str, "undernourished");
else You("look as %s as ever.",
ACURR(A_CHA) > 14 ?
(poly_gender()==1 ? "beautiful" : "handsome") :
"ugly");
} else {
You("can't see your %s %s.",
ACURR(A_CHA) > 14 ?
(poly_gender()==1 ? "beautiful" : "handsome") :
"ugly",
body_part(FACE));
}
return 1;
}
if(u.uswallow) {
if (!Blind) You("reflect %s's %s.", mon_nam(u.ustuck),
is_animal(u.ustuck->data)? "stomach" : "interior");
return 1;
}
if(Underwater) {
You("offer the fish a chance to do some makeup.");
return 1;
}
if(u.dz) {
if (!Blind)
You("reflect the %s.", (u.dz > 0) ? "floor" : "ceiling");
return 1;
}
if(!(mtmp = bhit(u.dx,u.dy,COLNO,INVIS_BEAM,
(int(*)())0,(int(*)())0,obj)) ||
!haseyes(mtmp->data))
return 1;
vis = canseemon(mtmp);
mlet = mtmp->data->mlet;
if(mtmp->msleep) {
if (vis)
pline ("%s is tired and doesn't look at your mirror.",
Monnam(mtmp));
} else if (!mtmp->mcansee) {
if (vis)
pline("%s can't see anything at the moment.", Monnam(mtmp));
/* some monsters do special things */
} else if (mlet == S_VAMPIRE || mlet == S_GHOST) {
if (vis)
pline ("%s doesn't seem to reflect anything.", Monnam(mtmp));
} else if(!mtmp->mcan && mtmp->data == &mons[PM_MEDUSA]) {
if (vis)
pline("%s is turned to stone!", Monnam(mtmp));
stoned = TRUE;
killed(mtmp);
} else if(!mtmp->mcan && !mtmp->minvis &&
mtmp->data == &mons[PM_FLOATING_EYE]) {
int tmp = d((int)mtmp->m_lev, (int)mtmp->data->mattk[0].damd);
if (!rn2(4)) tmp = 120;
/* Note: floating eyes cannot use their abilities while invisible,
* but Medusa and umber hulks can.
*/
if (vis)
pline("%s is frozen by its reflection.",Monnam(mtmp));
else You("hear something stop moving.");
mtmp->mcanmove = 0;
if ( (int) mtmp->mfrozen + tmp > 127)
mtmp->mfrozen = 127;
else mtmp->mfrozen += tmp;
} else if(!mtmp->mcan && mtmp->data == &mons[PM_UMBER_HULK]) {
if (vis)
pline ("%s has confused itself!", Monnam(mtmp));
mtmp->mconf = 1;
} else if(!mtmp->mcan && !mtmp->minvis && (mlet == S_NYMPH
|| mtmp->data==&mons[PM_SUCCUBUS])) {
if (vis) {
pline ("%s looks beautiful in your mirror.",Monnam(mtmp));
pline ("She decides to take it!");
} else pline ("It steals your mirror!");
setnotworn(obj); /* in case mirror was wielded */
freeinv(obj);
mpickobj(mtmp,obj);
rloc(mtmp);
} else if (mlet != S_UNICORN && !humanoid(mtmp->data) &&
(!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
if (vis)
pline ("%s is frightened by its reflection.",
Monnam(mtmp));
mtmp->mflee = 1;
mtmp->mfleetim += d(2,4);
} else if (!Blind) {
if (mtmp->minvis && !See_invisible)
;
else if ((mtmp->minvis && !perceives(mtmp->data))
|| !haseyes(mtmp->data))
pline("%s doesn't seem to be aware of its reflection.",
Monnam(mtmp));
else
pline("%s doesn't seem to mind %s reflection.",
Monnam(mtmp),
humanoid(mtmp->data) ? (mtmp->female ? "her" : "his")
: "its");
}
return 1;
}
static void
use_bell(obj)
register struct obj *obj;
{
You("ring %s.", the(xname(obj)));
if(Underwater) {
pline("But it sounds kind of muffled.");
return;
}
if(obj->otyp == BELL) {
if(u.uswallow) {
pline(nothing_happens);
return;
}
if(obj->cursed && !rn2(3)) {
register struct monst *mtmp;
if(mtmp = makemon(&mons[PM_WOOD_NYMPH], u.ux, u.uy))
You("summon %s!", a_monnam(mtmp));
}
wake_nearby();
return;
}
/* bell of opening */
if(u.uswallow && !obj->blessed) {
pline(nothing_happens);
return;
}
if(obj->cursed) {
coord mm;
mm.x = u.ux;
mm.y = u.uy;
mkundead(&mm);
cursed_bell:
wake_nearby();
if(obj->spe > 0) obj->spe--;
return;
}
if(invocation_pos(u.ux, u.uy) &&
!On_stairs(u.ux, u.uy) && !u.uswallow) {
pline("%s emits an unnerving high-pitched sound...",
The(xname(obj)));
obj->age = moves;
if(obj->spe > 0) obj->spe--;
wake_nearby();
obj->known = 1;
return;
}
if(obj->blessed) {
if(obj->spe > 0) {
register int cnt = openit();
if(cnt == -1) return; /* was swallowed */
switch(cnt) {
case 0: pline(nothing_happens); break;
case 1: pline("Something opens..."); break;
default: pline("Things open around you..."); break;
}
if(cnt > 0) obj->known = 1;
obj->spe--;
} else pline(nothing_happens);
} else { /* uncursed */
if(obj->spe > 0) {
register int cnt = findit();
if(cnt == 0) pline(nothing_happens);
else obj->known = 1;
obj->spe--;
} else {
if(!rn2(3)) goto cursed_bell;
else pline(nothing_happens);
}
}
}
static void
use_candelabrum(obj)
register struct obj *obj;
{
if(Underwater) {
You("can't make fire under water.");
return;
}
if(obj->lamplit) {
You("snuff the candle%s out.", obj->spe > 1 ? "s" : "");
obj->lamplit = 0;
check_lamps();
return;
}
if(obj->spe <= 0) {
pline("This %s has no candles.", xname(obj));
return;
}
if(u.uswallow || obj->cursed) {
pline("The candle%s flicker%s on for a moment, then die%s.",
obj->spe > 1 ? "s" : "",
obj->spe > 1 ? "" : "s",
obj->spe > 1 ? "" : "s");
return;
}
if(obj->spe < 7) {
pline("There %s only %d candle%s in %s.",
obj->spe == 1 ? "is" : "are",
obj->spe,
obj->spe > 1 ? "s" : "",
the(xname(obj)));
pline("%s lit. %s emits a dim light.",
obj->spe == 1 ? "It is" : "They are", The(xname(obj)));
} else {
pline("%s's candles burn%s", The(xname(obj)),
(Blind ? "." : " brightly!"));
}
if (!invocation_pos(u.ux, u.uy)) {
pline("The candle%s being rapidly consumed!",
(obj->spe > 1 ? "s are" : " is"));
obj->age /= 2;
} else {
if(obj->spe == 7)
pline("%s glows with a strange light!", The(xname(obj)));
obj->known = 1;
}
obj->lamplit = 1;
check_lamps();
}
static void
use_candle(obj)
register struct obj *obj;
{
register struct obj *otmp;
char qbuf[QBUFSZ];
if(obj->lamplit) {
use_lamp(obj);
return;
}
if(u.uswallow) {
You("don't have enough elbow-room to maneuver.");
return;
}
if(Underwater) {
pline("Sorry, fire and water don't mix.");
return;
}
for(otmp = invent; otmp; otmp = otmp->nobj) {
if(otmp->otyp == CANDELABRUM_OF_INVOCATION && otmp->spe < 7)
break;
}
if(!otmp || otmp->spe == 7) {
use_lamp(obj);
return;
}
Sprintf(qbuf, "Attach %s", the(xname(obj)));
Sprintf(eos(qbuf), " to %s?", the(xname(otmp)));
if(yn(qbuf) == 'n') {
You("try to light %s...", the(xname(obj)));
use_lamp(obj);
return;
} else {
register long needed = 7L - (long)otmp->spe;
You("attach %ld%s candle%s to %s.",
obj->quan >= needed ? needed : obj->quan,
!otmp->spe ? "" : " more",
(needed > 1L && obj->quan > 1L) ? "s" : "",
the(xname(otmp)));
if(otmp->lamplit)
pline("The new candle%s magically ignite%s!",
(needed > 1L && obj->quan > 1L) ? "s" : "",
(needed > 1L && obj->quan > 1L) ? "" : "s");
if(obj->unpaid)
You("use %s, you bought %s!",
(needed > 1L && obj->quan > 1L) ? "them" : "it",
(needed > 1L && obj->quan > 1L) ? "them" : "it");
if(!otmp->spe || otmp->age > obj->age)
otmp->age = obj->age;
if(obj->quan > needed) {
if(obj->unpaid) {
/* this is a hack, until we re-write the billing */
/* code to accommodate such cases directly. IM*/
register long delta = obj->quan - needed;
subfrombill(obj, shop_keeper(*u.ushops));
obj->quan = needed;
addtobill(obj, TRUE, FALSE, TRUE);
bill_dummy_object(obj);
obj->quan = delta;
addtobill(obj, TRUE, FALSE, TRUE);
} else {
obj->quan -= needed;
}
otmp->spe += (int)needed;
} else {
otmp->spe += (int)obj->quan;
freeinv(obj);
obfree(obj, (struct obj *)0);
}
if(needed < 7L && otmp->spe == 7)
pline("%s has now seven%s candles attached.",
The(xname(otmp)), otmp->lamplit ? " lit" : "");
}
}
boolean
snuff_candle(otmp) /* call in drop, throw, and put in box, etc. */
register struct obj *otmp;
{
register boolean candle = Is_candle(otmp);
if ((candle || otmp->otyp == CANDELABRUM_OF_INVOCATION) &&
otmp->lamplit) {
register boolean many = candle ? otmp->quan > 1L : otmp->spe > 1;
pline("The %scandle%s flame%s extinguished.",
(candle ? "" : "candelabrum's "),
(many ? "s'" : "'s"), (many ? "s are" : " is"));
otmp->lamplit = 0;
check_lamps();
return(TRUE);
}
return(FALSE);
}
boolean
snuff_lit(obj)
struct obj *obj;
{
if(obj->lamplit) {
if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == BRASS_LANTERN) {
Your("lamp is now off.");
obj->lamplit = 0;
check_lamps();
return(TRUE);
}
if(snuff_candle(obj)) return(TRUE);
}
return(FALSE);
}
static void
use_lamp(obj)
struct obj *obj;
{
if(Underwater) {
pline("This is not a diving lamp.");
return;
}
if(obj->lamplit) {
if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == BRASS_LANTERN)
Your("lamp is now off.");
else
You("snuff out %s.", the(xname(obj)));
obj->lamplit = 0;
check_lamps();
return;
}
if (!Is_candle(obj) && obj->spe <= 0) {
if (obj->otyp == BRASS_LANTERN)
Your("lamp has run out of power.");
else pline("This %s has no oil.", xname(obj));
return;
}
if(obj->cursed && !rn2(2))
pline("%s flicker%s on for a moment, then die%s.",
The(xname(obj)),
obj->quan > 1L ? "" : "s",
obj->quan > 1L ? "" : "s");
else {
if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == BRASS_LANTERN)
Your("lamp is now on.");
else
pline("%s%s flame%s burn%s%s", The(xname(obj)),
obj->quan > 1L ? "'" : "'s",
obj->quan > 1L ? "s" : "",
obj->quan > 1L ? "" : "s",
Blind ? "." : " brightly!");
obj->lamplit = 1;
check_lamps();
if (obj->unpaid && Is_candle(obj) &&
obj->age == 20L * (long)objects[obj->otyp].oc_cost) {
const char *it_them = obj->quan > 1L ? "them" : "it";
You("use %s, you've bought %s!", it_them, it_them);
bill_dummy_object(obj);
}
}
}
void
check_lamps()
{
register struct obj *obj;
int lamps = 0;
for(obj = invent; obj; obj = obj->nobj)
if (obj->lamplit) {
lamps++;
break;
}
if (lamps && u.nv_range == 1) {
u.nv_range = 3;
vision_full_recalc = 1;
} else if (!lamps && u.nv_range == 3) {
u.nv_range = 1;
vision_full_recalc = 1;
}
}
static const char NEARDATA cuddly[] = { TOOL_CLASS, 0 };
int
dorub()
{
struct obj *obj = getobj(cuddly, "rub");
if(!obj || (obj != uwep && !wield_tool(obj))) return 0;
/* now uwep is obj */
if (uwep->otyp == MAGIC_LAMP) {
if (uwep->spe > 0 && !rn2(3)) {
djinni_from_bottle(uwep);
makeknown(MAGIC_LAMP);
uwep->otyp = OIL_LAMP;
uwep->spe = 1; /* for safety */
uwep->age = rn1(500,1000);
} else if (rn2(2) && !Blind)
You("see a puff of smoke.");
else pline(nothing_happens);
} else if (obj->otyp == BRASS_LANTERN) {
/* message from Adventure */
pline("Rubbing the electric lamp is not particularly rewarding.");
pline("Anyway, nothing exciting happens.");
} else pline(nothing_happens);
return 1;
}
int
dojump()
{
coord cc;
register struct monst *mtmp;
if (!Jumping || Levitation) {
You("can't jump very far.");
return 0;
} else if (u.uswallow) {
pline("You've got to be kidding!");
return 0;
} else if (u.uinwater) {
pline("This calls for swimming, not jumping!");
return 0;
} else if (u.ustuck) {
You("cannot escape from %s!", mon_nam(u.ustuck));
return 0;
} else if (near_capacity() > UNENCUMBERED) {
You("are carrying too much to jump!");
return 0;
} else if (u.uhunger <= 100 || ACURR(A_STR) < 6) {
You("lack the strength to jump!");
return 0;
}
pline("Where do you want to jump?");
cc.x = u.ux;
cc.y = u.uy;
getpos(&cc, TRUE, "the desired position");
if(cc.x == -10) return 0; /* user pressed esc */
if (!(Jumping & ~INTRINSIC) && distu(cc.x, cc.y) != 5) {
pline("Illegal move!");
return 0;
} else if (distu(cc.x, cc.y) > 9) {
pline("Too far!");
return 0;
} else if (!cansee(cc.x, cc.y)) {
You("cannot see where to land!");
return 0;
} else if (mtmp = m_at(cc.x, cc.y)) {
You("cannot trample %s!", mon_nam(mtmp));
return 0;
} else if (!isok(cc.x, cc.y) ||
#ifdef POLYSELF
(IS_ROCK(levl[cc.x][cc.y].typ) && !passes_walls(uasmon)) ||
#else
IS_ROCK(levl[cc.x][cc.y].typ) ||
#endif
sobj_at(BOULDER, cc.x, cc.x) ) {
You("cannot jump there!");
return 0;
} else {
if(u.utrap)
switch(u.utraptype) {
case TT_BEARTRAP: {
register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
You("rip yourself out of the bear trap! Ouch!");
losehp(rnd(10), "jumping out of a bear trap", KILLED_BY);
set_wounded_legs(side, rn1(1000,500));
break;
}
case TT_PIT:
You("leap from the pit!");
break;
case TT_WEB:
You("tear the web apart as you pull yourself free!");
deltrap(t_at(u.ux,u.uy));
break;
case TT_LAVA:
You("pull yourself above the lava!");
u.utrap = 0;
return 1;
case TT_INFLOOR:
You("strain your %s, but are still stuck in the floor.",
makeplural(body_part(LEG)));
set_wounded_legs(LEFT_SIDE, rn1(10, 11));
set_wounded_legs(RIGHT_SIDE, rn1(10, 11));
return 1;
}
teleds(cc.x, cc.y);
nomul(-1);
nomovemsg = "";
morehungry(rnd(25));
return 1;
}
}
static void
use_tinning_kit(obj)
register struct obj *obj;
{
register struct obj *corpse, *can;
/* This takes only 1 move. If this is to be changed to take many
* moves, we've got to deal with decaying corpses...
*/
if (!(corpse = floorfood("can", 1))) return;
if (corpse->oeaten) {
You("cannot tin something which is partly eaten.");
return;
}
if ((corpse->corpsenm == PM_COCKATRICE)
#ifdef POLYSELF
&& !resists_ston(uasmon)
#endif
&& !uarmg) {
pline("Tinning a cockatrice corpse without gloves was not a very wise move...");
#if defined(POLYSELF)
/* this will have to change if more monsters can poly */
if(!(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM)))
#endif
{
You("turn to stone...");
killer_format = KILLED_BY;
killer = "trying to tin a cockatrice without gloves";
done(STONING);
}
}
if (mons[corpse->corpsenm].cnutrit == 0) {
You("can't tin something that insubstantial!");
return;
}
if (is_rider(&mons[corpse->corpsenm])) {
revive_corpse(corpse, 0, FALSE);
verbalize("Yes.... But War does not preserve its enemies...");
return;
}
if(can = mksobj(TIN, FALSE, FALSE)) {
can->corpsenm = corpse->corpsenm;
can->cursed = obj->cursed;
can->blessed = obj->blessed;
can->owt = weight(can);
can->known = 1;
can->spe = -1; /* Mark tinned tins. No spinach allowed... */
can = hold_another_object(can, "You make, but cannot pick up, %s.",
doname(can), (const char *)0);
if (carried(corpse)) useup(corpse);
else useupf(corpse);
} else impossible("Tinning failed.");
}
void
use_unicorn_horn(obj)
struct obj *obj;
{
boolean blessed = (obj && obj->blessed);
boolean did_something = FALSE;
if (obj && obj->cursed) {
switch (rn2(6)) {
static char buf[BUFSZ];
case 0: make_sick(Sick ? 1L : (long) rn1(20, 20), TRUE);
Strcpy(buf, xname(obj));
u.usick_cause = (const char *)buf;
break;
case 1: make_blinded(Blinded + (long) rnd(100), TRUE);
break;
case 2: if (!Confusion)
You("suddenly feel %s.",
Hallucination ? "trippy" : "confused");
make_confused(HConfusion + (long) rnd(100), TRUE);
break;
case 3: make_stunned(HStun + (long) rnd(100), TRUE);
break;
case 4: (void) adjattrib(rn2(6), -1, FALSE);
break;
case 5: make_hallucinated(HHallucination + (long) rnd(100),
TRUE, 0L);
break;
}
return;
}
if (Sick) {
make_sick(0L, TRUE);
did_something++;
}
if (Blinded > (long)(u.ucreamed+1) && (!did_something || blessed)) {
make_blinded(u.ucreamed ? (long)(u.ucreamed+1) : 0L, TRUE);
did_something++;
}
if (Hallucination && (!did_something || blessed)) {
make_hallucinated(0L, TRUE, 0L);
did_something++;
}
if (Vomiting && (!did_something || blessed)) {
make_vomiting(0L, TRUE);
did_something++;
}
if (HConfusion && (!did_something || blessed)) {
make_confused(0L, TRUE);
did_something++;
}
if (HStun && (!did_something || blessed)) {
make_stunned(0L, TRUE);
did_something++;
}
if (!did_something || blessed) {
register int j;
int did_stat = 0;
int i = rn2(A_MAX);
for(j=0; j<A_MAX; j++) {
/* don't recover strength lost while hungry */
if ((blessed || j==i) &&
((j != A_STR || u.uhs < WEAK)
? (ABASE(i) < AMAX(i))
: (ABASE(A_STR) < (AMAX(A_STR) - 1)))) {
did_something++;
/* They may have to use it several times... */
if (!did_stat) {
did_stat++;
pline("This makes you feel good!");
}
ABASE(i)++;
flags.botl = 1;
}
}
}
if (!did_something) pline(nothing_happens);
}
static void
use_figurine(obj)
register struct obj *obj;
{
xchar x, y;
if(!getdir(NULL)) {
flags.move = multi = 0;
return;
}
x = u.ux + u.dx; y = u.uy + u.dy;
if (!isok(x,y)) {
You("can't seem to put the figurine there.");
return;
}
if (IS_ROCK(levl[x][y].typ) && !passes_walls(&mons[obj->corpsenm])) {
You("can't place a figurine in solid rock!");
return;
}
if (sobj_at(BOULDER,x,y) && !passes_walls(&mons[obj->corpsenm])
&& !throws_rocks(&mons[obj->corpsenm])) {
You("can't fit the figurine on the boulder.");
return;
}
You("%s and it transforms.",
(u.dx||u.dy) ? "set the figurine besides you" :
(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) ?
"release the figurine" :
(u.dz < 0 ?
"toss the figurine into the air" :
"set the figurine on the ground"));
make_familiar(obj, u.ux+u.dx, u.uy+u.dy);
useup(obj);
}
static void
use_grease(obj)
struct obj *obj;
{
struct obj *otmp;
if (obj->spe > 0) {
char allow_all[2];
if (obj->cursed && !rn2(2)) {
pline("The %s slips from your fingers!",xname(obj));
dropx(obj);
obj->spe -= 1;
return;
}
allow_all[0] = ALL_CLASSES; allow_all[1] = '\0';
otmp = getobj(allow_all,"grease");
if (otmp) {
You("cover your %s with a thick layer of grease.",xname(otmp));
otmp->greased = 1;
obj->spe -= 1;
}
}
}
int
doapply()
{
register struct obj *obj;
register int res = 1;
if(check_capacity(NULL)) return (0);
obj = getobj(tools, "use or apply");
if(!obj) return 0;
check_unpaid(obj);
switch(obj->otyp){
case BLINDFOLD:
if (obj == ublindf) {
if(cursed(obj)) break;
else Blindf_off(obj);
}
else if (!ublindf) Blindf_on(obj);
else You("are already %s", ublindf->otyp == TOWEL ?
"covered by a towel." : "wearing a blindfold!");
break;
case LARGE_BOX:
case CHEST:
case ICE_BOX:
case SACK:
case BAG_OF_HOLDING:
case OILSKIN_SACK:
res = use_container(obj, 1);
break;
case BAG_OF_TRICKS:
if(obj->spe > 0) {
register int cnt = 1;
obj->spe -= 1;
if(!rn2(23)) cnt += rn2(7) + 1;
while(cnt--)
(void) makemon((struct permonst *) 0, u.ux, u.uy);
makeknown(BAG_OF_TRICKS);
} else
pline(nothing_happens);
break;
case CAN_OF_GREASE:
use_grease(obj);
break;
case LOCK_PICK:
#ifdef TOURIST
case CREDIT_CARD:
#endif
case SKELETON_KEY:
(void) pick_lock(obj);
break;
case PICK_AXE:
res = use_pick_axe(obj);
break;
case TINNING_KIT:
use_tinning_kit(obj);
break;
#ifdef WALKIES
case LEASH:
use_leash(obj);
break;
#endif
case MAGIC_WHISTLE:
use_magic_whistle(obj);
break;
case TIN_WHISTLE:
use_whistle(obj);
break;
case STETHOSCOPE:
res = 0;
use_stethoscope(obj);
break;
case MIRROR:
res = use_mirror(obj);
break;
case BELL:
case BELL_OF_OPENING:
use_bell(obj);
break;
case CANDELABRUM_OF_INVOCATION:
use_candelabrum(obj);
break;
case WAX_CANDLE:
case TALLOW_CANDLE:
use_candle(obj);
break;
case OIL_LAMP:
case MAGIC_LAMP:
case BRASS_LANTERN:
use_lamp(obj);
break;
#ifdef TOURIST
case EXPENSIVE_CAMERA:
res = use_camera(obj);
break;
#endif
case TOWEL:
res = use_towel(obj);
break;
case CRYSTAL_BALL:
use_crystal_ball(obj);
break;
case MAGIC_MARKER:
res = dowrite(obj);
break;
case TIN_OPENER:
if(!carrying(TIN)) {
You("have no tin to open.");
goto xit;
}
You("cannot open a tin without eating or discarding its contents.");
if(flags.verbose)
pline("In order to eat, use the 'e' command.");
if(obj != uwep)
pline("Opening the tin will be much easier if you wield the tin opener.");
goto xit;
case FIGURINE:
use_figurine(obj);
break;
case UNICORN_HORN:
use_unicorn_horn(obj);
break;
case WOODEN_FLUTE:
case MAGIC_FLUTE:
case TOOLED_HORN:
case FROST_HORN:
case FIRE_HORN:
case WOODEN_HARP:
case MAGIC_HARP:
case BUGLE:
case LEATHER_DRUM:
case DRUM_OF_EARTHQUAKE:
res = do_play_instrument(obj);
break;
case HORN_OF_PLENTY:
if (obj->spe > 0) {
struct obj *otmp;
const char *what;
#ifdef MAC
char melody [ 3 ] = { 0 , 0 , 0 } ;
melody [ 0 ] = rn2 ( 8 ) + 'A' ;
melody [ 1 ] = rn2 ( 8 ) + 'A' ;
mac_speaker ( obj , & melody ) ;
#endif
obj->spe -= 1;
if (!rn2(13)) {
otmp = mkobj(POTION_CLASS, FALSE);
if (objects[otmp->otyp].oc_magic) do {
otmp->otyp = rnd_class(POT_BOOZE, POT_WATER);
} while (otmp->otyp == POT_SICKNESS);
what = "A potion";
} else {
otmp = mkobj(FOOD_CLASS, FALSE);
if (otmp->otyp == FOOD_RATION && !rn2(7))
otmp->otyp = LUMP_OF_ROYAL_JELLY;
what = "Some food";
}
pline("%s spills out.", what);
otmp->blessed = obj->blessed;
otmp->cursed = obj->cursed;
otmp->owt = weight(otmp);
otmp = hold_another_object(otmp, u.uswallow ?
"Oops! %s away from you!" :
"Oops! %s to the floor!",
The(aobjnam(otmp, "slip")),
(const char *)0);
makeknown(HORN_OF_PLENTY);
} else
pline(nothing_happens);
break;
default:
pline("Sorry, I don't know how to use that.");
xit:
nomul(0);
return 0;
}
nomul(0);
return res;
}
#endif /* OVLB */
/*apply.c*/